#!/bin/bash
#Author: YangYi
#Date: 2025-06-21
#Version: v1
#Content nginx配置文件基线漏洞修复
#1. 遍历节点所有配置文件并添加漏洞修复参数


# ---------------------------初始化全局变量----------------------------

#格式化时间
TIME=`date +%Y-%m-%d-%H:%M:%S`

# ----------------------------功能模块函数-----------------------------


# 查找所有nginx.conf配置文件
find_nginx_configs() {
    find / -type f -name "nginx.conf" | grep -v "docker\|traefik" 2>/dev/null
    #find / -type f -name "nginx.conf" 2>/dev/null
}

# 检查配置是否已存在
config_exists() {
    local file=$1
    local pattern=$2
    if grep -q "$pattern" "$file"; then
        return 0
    else
        return 1
    fi
}

# 在http块中添加配置
add_http_config() {
    local file=$1
    local temp_file=$(mktemp)
    
    # 检查并添加各项配置
    config_exists "$file" "limit_conn_zone" || sed -i "/http {/a\    limit_conn_zone \$binary_remote_addr zone=addr:10m;  # 每个IP的连接限制" "$file" > /dev/null 2>&1
    config_exists "$file" "server_tokens off" || sed -i "/http {/a\    server_tokens off;  # 隐藏Nginx版本号" "$file" > /dev/null 2>&1
    config_exists "$file" "client_header_timeout" || sed -i "/http {/a\    client_header_timeout 300;   # 客户端请求头超时时间" "$file" > /dev/null 2>&1
    config_exists "$file" "client_body_timeout" || sed -i "/http {/a\    client_body_timeout 300;     # 请求体超时" "$file" > /dev/null 2>&1
    config_exists "$file" "keepalive_timeout" || sed -i "/http {/a\    keepalive_timeout 300;      # 连接超时时间" "$file" > /dev/null 2>&1
    config_exists "$file" "keepalive_requests" || sed -i "/http {/a\    keepalive_requests 100;    # 单个连接的最大请求数" "$file" > /dev/null 2>&1
    config_exists "$file" "send_timeout" || sed -i "/http {/a\    send_timeout 30;           # 客户端响应超时" "$file" > /dev/null 2>&1
    
    rm -f "$temp_file"
}

# 在server块中添加配置
add_server_config() {
    local file=$1
    local temp_file=$(mktemp)
    
    # 检查并添加各项配置
    config_exists "$file" "error_page 400 404 413 /404.html" || sed -i "/server {/a\             error_page 400 404 413 /404.html;" "$file" > /dev/null 2>&1
    config_exists "$file" "error_page 500 502 503 504 /50x.html" || sed -i "/server {/a\             error_page 500 502 503 504 /50x.html;" "$file" > /dev/null 2>&1
    
    rm -f "$temp_file"
}

# 在location块中添加配置
add_location_config-1() {
    local file=$1
    local temp_file=$(mktemp)

    # 检查并添加各项配置
    #config_exists "$file" "limit_conn addr 100" || sed -i "/location  {/a\        limit_conn addr 100;" "$file" > /dev/null 2>&1
    config_exists "$file" "limit_rate 10240k" || sed -i '/location [^{]*{/,/}/ {
                                                       /}/i            limit_rate 10240k;  # 限速10MB/s
                                                   }' "$file" > /dev/null 2>&1
    config_exists "$file" "limit_conn addr 100" || sed -i '/location [^{]*{/,/}/ {
                                                       /}/i            limit_conn addr 100;  # 每个IP最多100个连接
                                                   }' "$file" > /dev/null 2>&1
    
    rm -f "$temp_file"
}

# 在location块中添加配置
add_location_config() {
    local file=$1
    local temp_file=$(mktemp)

    cp "$file" "$temp_file"

    for config in "limit_conn addr 100"; do
        if ! config_exists "$file" "$config"; then
            awk -v config="$config" '
            /^[[:space:]]*location[[:space:]]+[^{]*{/ {
                in_location = 1
                if ($0 ~ /^[[:space:]]*#/) {
                    in_commented_location = 1
                } else {
                    in_commented_location = 0
                }
                print
                next
            }
            in_location && /}/ {
                if (!in_commented_location && !config_added) {
                    printf "            %s;  # 自动添加的配置\n", config
                    config_added = 1
                }
                in_location = 0
                in_commented_location = 0
                config_added = 0
                print
                next
            }
            in_location && !in_commented_location {
                if (!/^[[:space:]]*#/) {
                    print
                }
                next
            }
            {
                if (!in_location || in_commented_location) {
                    print
                }
            }
            ' "$temp_file" > "$file"
        fi
    done

    for config in "limit_rate 10240k"; do
        if ! config_exists "$file" "$config"; then
            awk -v config="$config" '
            /^[[:space:]]*location[[:space:]]+[^{]*{/ {
                in_location = 1
                if ($0 ~ /^[[:space:]]*#/) {
                    in_commented_location = 1
                } else {
                    in_commented_location = 0
                }
                print
                next
            }
            in_location && /}/ {
                if (!in_commented_location && !config_added) {
                    printf "            %s;  # 自动添加的配置\n", config
                    config_added = 1
                }
                in_location = 0
                in_commented_location = 0
                config_added = 0
                print
                next
            }
            in_location && !in_commented_location {
                if (!/^[[:space:]]*#/) {
                    print
                }
                next
            }
            {
                if (!in_location || in_commented_location) {
                    print
                }
            }
            ' "$temp_file" > "$file"
        fi
    done

    rm -f "$temp_file"
}

# 主函数
main() {
    configs=$(find_nginx_configs)
    
    if [ -z "$configs" ]; then
        echo "未找到任何nginx.conf配置文件"
        exit 1
    fi
    
    echo "--------------------------------------------- 找到以下nginx.conf配置文件 ---------------------------------------------"
    echo "$configs"
    
    for config in $configs; do
        
        # 备份原始文件
        cp "$config" "$config.bak-$TIME"
        
        # 添加http配置
        add_http_config "$config"
        
        # 添加server配置
        add_server_config "$config"
        
        # 添加location配置
        add_location_config "$config"
        
    done
    
    echo "所有配置文件处理完成"
}

# 执行主函数
main
